Skip to content

feat: expose headless wallet list imperatively on the AppKit client#5695

Merged
0xmkh merged 5 commits into
mainfrom
feat/headless-wallets-on-client
Jun 26, 2026
Merged

feat: expose headless wallet list imperatively on the AppKit client#5695
0xmkh merged 5 commits into
mainfrom
feat/headless-wallets-on-client

Conversation

@enesozturk

Copy link
Copy Markdown
Contributor

What

Exposes the headless wallet list imperatively on the AppKit client, so a non-React host can list / search / connect wallets without the useAppKitWallets React hook.

Why

The headless wallet flow — list/search/paginate WalletGuide wallets, fetch the WalletConnect URI, and programmatically connect injected / API / mobile-deeplink wallets — lived only inside the useAppKitWallets React hook (packages/controllers/exports/react.ts), reaching into the controllers and re-implementing the connect logic. A non-React consumer (e.g. @walletconnect/pay-appkit, which drives a fully custom checkout) has no way to reach it.

This lifts the imperative core onto the client so React and non-React hosts share one tested code path.

Changes

  • HeadlessWalletUtil (new, @reown/appkit-controllers) — the framework-neutral core: fetchWallets / getWalletList / subscribeWalletList / getWalletConnectUri / connect / resetWcUri / resetConnectingWallet. Reads/writes the global controllers directly (no AppKit instance), exactly like ConnectionControllerUtil. The connect logic (injected → API-wallet fallback → mobile deeplink → WalletConnect) is lifted verbatim from the hook.
  • AppKit client methods (appkit-base-client.ts): appKit.fetchWallets(options?), appKit.getWalletList(), appKit.subscribeWalletList(cb), appKit.getWalletConnectUri(options?), appKit.connectWallet(wallet, namespace?, options?) — each delegating to HeadlessWalletUtil.
  • ConnectOptions / FetchWalletsOptions now have a single home in HeadlessWalletUtil; the hook re-exports them (resolves the previous duplicate-definition).

getWalletInfo / getApprovedCaipNetworkIds / getAccount / subscribeAccount / subscribeConnections (which carry wcUri / wcError) already exist on the client, so no new surface was needed for connected-wallet info or the WC URI state.

Follow-up (intentionally out of scope)

Refactor useAppKitWallets to delegate its connect / fetchWallets / getWcUri bodies to HeadlessWalletUtil (dedup the logic). Kept out to keep this diff additive; the hook already shares the option types and is unaffected behaviorally.

Validation

  • @reown/appkit-controllers build ✅ · @reown/appkit build ✅
  • HeadlessWalletUtil unit tests — 14/14 (fetch/search/list, the full connect matrix incl. mobile deeplink, WC URI, resets)
  • Existing useAppKitWallets hook tests — 45/45 (unchanged)
  • Lint clean on the changed files

Context

Enables @walletconnect/pay-appkit (the WalletConnect Pay headless SDK adapter) to drive headless wallet listing/connect from a framework-neutral entry — and any pure-JS host to do the same — instead of being limited to the React hook.

enesozturk and others added 2 commits June 26, 2026 16:10
The headless wallet flow (list/search/paginate WalletGuide wallets, fetch the WC URI,
and programmatic connect for injected/API/mobile wallets) lived only inside the
`useAppKitWallets` React hook, so non-React hosts couldn't drive it. Lift the imperative
core into a new `HeadlessWalletUtil` (@reown/appkit-controllers) and expose it on the
AppKit client:

- AppKit instance methods: fetchWallets / getWalletList / subscribeWalletList /
  getWalletConnectUri / connectWallet.
- HeadlessWalletUtil holds the shared logic (reads/writes the global controllers, no
  AppKit instance — same pattern as ConnectionControllerUtil), so the client methods and
  the React hook share one code path.

Follow-up: refactor useAppKitWallets to delegate to HeadlessWalletUtil (dedup); kept
out of this change to keep the diff additive.

+ HeadlessWalletUtil unit tests, changeset.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The hook redefined ConnectOptions/FetchWalletsOptions that now live in
HeadlessWalletUtil; re-export them from there (one declaration) to resolve the
ambiguous re-export in @reown/appkit's react build. Drop the now-unused BadgeType
import + tidy comment/cast lint.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Jun 26, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: f633c68

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 26 packages
Name Type
@reown/appkit-utils Patch
@reown/appkit Patch
@reown/appkit-cdn Patch
@reown/appkit-cli Patch
@reown/appkit-codemod Patch
@reown/appkit-common Patch
@reown/appkit-core Patch
@reown/appkit-experimental Patch
@reown/appkit-pay Patch
@reown/appkit-polyfills Patch
@reown/appkit-scaffold-ui Patch
@reown/appkit-siwe Patch
@reown/appkit-siwx Patch
@reown/appkit-testing Patch
@reown/appkit-ui Patch
@reown/appkit-universal-connector Patch
@reown/appkit-wallet-button Patch
@reown/appkit-wallet Patch
@reown/appkit-controllers Patch
@reown/appkit-adapter-bitcoin Patch
@reown/appkit-adapter-ethers Patch
@reown/appkit-adapter-ethers5 Patch
@reown/appkit-adapter-solana Patch
@reown/appkit-adapter-ton Patch
@reown/appkit-adapter-tron Patch
@reown/appkit-adapter-wagmi Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@enesozturk enesozturk left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we also dogfood this in examples/html-headless project? build a very simple wallet modal where it has:

  • list first page
  • has infinite loading

@@ -0,0 +1,8 @@
---
'@reown/appkit-controllers': minor

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add all packages here, not just the affected ones

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in d5d9655 — the changeset now lists all packages (repo lockstep convention).

@vercel

vercel Bot commented Jun 26, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
appkit-demo Ready Ready Preview, Comment Jun 26, 2026 2:05pm
appkit-gallery Ready Ready Preview Jun 26, 2026 2:05pm
appkit-headless-sample-app Ready Ready Preview, Comment Jun 26, 2026 2:05pm
appkit-laboratory Ready Ready Preview Jun 26, 2026 2:05pm
9 Skipped Deployments
Project Deployment Actions Updated (UTC)
appkit-basic-example Ignored Ignored Jun 26, 2026 2:05pm
appkit-basic-sign-client-example Ignored Ignored Jun 26, 2026 2:05pm
appkit-basic-up-example Ignored Ignored Jun 26, 2026 2:05pm
appkit-ethers5-bera Ignored Ignored Jun 26, 2026 2:05pm
appkit-nansen-demo Ignored Ignored Jun 26, 2026 2:05pm
appkit-wagmi-cdn-example Ignored Ignored Jun 26, 2026 2:05pm
ethereum-provider-wagmi-example Ignored Ignored Jun 26, 2026 2:05pm
next-wagmi-solana-bitcoin-example Ignored Ignored Jun 26, 2026 2:05pm
vue-wagmi-example Ignored Ignored Jun 26, 2026 2:05pm

Request Review

@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Visual Regression Test Results ✅ Passed

⚠️ 20 visual change(s) detected

Chromatic Build: https://www.chromatic.com/build?appId=6493191bf4b10fed8ca7353f&number=942
Storybook Preview: https://6493191bf4b10fed8ca7353f-dqtgvwuscs.chromatic.com/

👉 Please review the visual changes in Chromatic and accept or reject them.

@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

📦 Bundle Size Check

All bundles are within size limits

📊 View detailed bundle sizes

> @reown/appkit-monorepo@1.7.1 size /home/runner/work/appkit/appkit


> size-limit

@reown/appkit - Main Entry
Size limit:   80 kB
Size:         75.84 kB with all dependencies, minified and gzipped
Loading time: 1.5 s    on slow 3G
Running time: 810 ms   on Snapdragon 410
Total time:   2.3 s
@reown/appkit/react
Size limit:   236 kB
Size:         235.08 kB with all dependencies, minified and gzipped
Loading time: 4.6 s     on slow 3G
Running time: 1.2 s     on Snapdragon 410
Total time:   5.8 s
@reown/appkit/vue
Size limit:   80 kB
Size:         75.84 kB with all dependencies, minified and gzipped
Loading time: 1.5 s    on slow 3G
Running time: 720 ms   on Snapdragon 410
Total time:   2.3 s
@reown/appkit-scaffold-ui
Size limit:   220 kB
Size:         214.38 kB with all dependencies, minified and gzipped
Loading time: 4.2 s     on slow 3G
Running time: 1.4 s     on Snapdragon 410
Total time:   5.6 s
@reown/appkit-ui
Size limit:   500 kB
Size:         13.16 kB with all dependencies, minified and gzipped
Loading time: 258 ms   on slow 3G
Running time: 505 ms   on Snapdragon 410
Total time:   762 ms

…less

- changeset: list all packages (repo lockstep convention), per review.
- examples/html-headless: a vanilla-JS wallet modal driven entirely by the new
  imperative client API — first page via appKit.fetchWallets({ page }), infinite
  loading on scroll (appends), live re-render via subscribeWalletList, and
  connectWallet on click. No React, no AppKit modal. Builds clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@enesozturk

Copy link
Copy Markdown
Contributor Author

Added examples/html-headless (d5d9655) — a vanilla-JS custom wallet modal driven entirely by the new imperative client API:

  • first page via appKit.fetchWallets({ page })appKit.getWalletList()
  • infinite loading on scroll — fetchWallets({ page: ++page }) appends, re-rendered live via appKit.subscribeWalletList(...)
  • connect on click via appKit.connectWallet(wallet, 'eip155'), account shown via subscribeAccount

No React, no AppKit modal. Builds clean (vite build ✓).

@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 78.49% 40039 / 51009
🔵 Statements 78.49% 40039 / 51009
🔵 Functions 76.11% 4277 / 5619
🔵 Branches 86.68% 9776 / 11277
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/adapters/tron/src/connectors/TronWalletConnectConnector.ts 77.6% 57.14% 30.76% 77.6% 36-37, 40-41, 44-45, 48-51, 54-57, 63-64, 80-81, 90-91, 169-170, 174-175, 178-179, 189-190
packages/appkit/src/client/appkit-base-client.ts 73.24% 85.66% 74.18% 73.24% 189-195, 215, 228-231, 234, 246-247, 253-254, 257, 266, 313-314, 360-361, 399-400, 402-403, 408-409, 491-492, 528-534, 605-606, 628-643, 646, 684, 725-729, 736-737, 740-741, 746-747, 758-781, 790-791, 808-828, 832-853, 856-882, 885-891, 894-900, 903-909, 912-918, 921-931, 934-940, 943-950, 964-973, 976-982, 985-986, 989-990, 1009-1010, 1033-1073, 1080-1092, 1098-1125, 1128-1138, 1170-1171, 1196-1197, 1202, 1217-1233, 1247, 1251-1259, 1290-1291, 1310-1313, 1317-1318, 1320-1321, 1355-1357, 1361-1382, 1387-1388, 1396-1397, 1399-1400, 1494-1495, 1507-1508, 1513, 1536-1541, 1588, 1609-1610, 1619, 1621-1637, 1642, 1688-1689, 1701-1712, 1759-1776, 1821, 1827-1831, 1852-1867, 1870-1871, 1897-1900, 1936-1955, 1987, 2030-2031, 2037-2063, 2293-2294, 2337-2338, 2342-2343, 2347-2348, 2355-2356, 2363-2368, 2376-2377, 2380-2381, 2397-2400, 2403-2404, 2424-2425, 2428-2429, 2450, 2471-2472, 2480-2481, 2493-2494, 2508, 2535-2536, 2542-2543, 2577-2582, 2600-2601, 2604-2605, 2652-2653, 2724-2725, 2728-2729, 2732-2735, 2738-2739, 2742-2743, 2746-2747, 2750-2751, 2754-2758, 2767-2776, 2785-2796, 1380, 2366
packages/controllers/exports/index.ts 100% 100% 100% 100%
packages/controllers/exports/react.ts 77.26% 87.64% 53.84% 77.26% 76-83, 85, 91, 100, 106, 108-117, 124, 133, 148-151, 164, 169, 174, 178, 183-185, 189, 196, 204, 213, 219, 225, 231, 233, 237, 239, 244, 273, 288, 294, 302, 306, 314-316, 437-438, 451-455, 461, 467, 475, 481-485, 505-506, 519-523, 535, 539-540, 542-550, 559, 565, 567-570, 573, 594, 73-80, 109, 156, 546, 568
packages/controllers/src/utils/HeadlessWalletUtil.ts 90.62% 96.42% 84.61% 90.62% 112-119, 147, 161
Generated in workflow #17156 for commit f633c68 by the Vitest Coverage Report Action

Apply prettier to the touched files and convert the new client-method header to a
block comment (multiline-comment-style / capitalized-comments lint).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
`TronWalletConnectConnector.ts` (from #5694, current main) has 4 consecutive line
comments that violate `multiline-comment-style`, failing `code_style (lint)` for every
branch off main. Convert to a block comment to unblock CI. Unrelated to this PR's
changes, but main's lint is red without it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@0xmkh 0xmkh deleted the feat/headless-wallets-on-client branch June 26, 2026 14:43
@github-actions github-actions Bot locked and limited conversation to collaborators Jun 26, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants